﻿using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Hont
{
    public static class GradientTextHelper
    {
        public static IEnumerator GradientText(string textIn, UILabel textOut)
        {
            return GradientText(textIn, textOut, Color.white);
        }

        public static IEnumerator GradientText(string textIn, UILabel textOut, Color defaultColor, float gradientWidth = 0.2f, float duration = 1f)
        {
            return GradientText(textIn, (text) =>
            {
                textOut.text = text;
            }, defaultColor, gradientWidth, duration);
        }

        public static IEnumerator GradientText(string textIn, Action<string> textOut, Color defaultColor, float gradientWidth, float duration)
        {
            var sb = new StringBuilder();
            return GradientText(textIn, textOut, sb, defaultColor, gradientWidth, duration);
        }

        public static IEnumerator GradientText(string textIn, Action<string> textOut, StringBuilder cacheSB, Color defaultColor, float gradientWidth, float duration)
        {
            Func<float, string> convertSourceText = (weight) =>
              {
                  var textLength_f = (float)textIn.Length;

                  for (int i = 0, iMax = textIn.Length; i < iMax; i++)
                  {
                      var singleChar = textIn[i];

                      if (singleChar == '\n' || singleChar == '\r')
                      {
                          cacheSB.Append(singleChar);
                          continue;
                      }

                      var relativeWeight = (i + 1) / textLength_f;
                      var substract = weight - relativeWeight;

                      var t = 0f;

                      if (substract < 0)
                      {
                          var gradientT = Mathf.Clamp01((-substract) / (gradientWidth + Mathf.Epsilon));
                          t = Mathf.Lerp(1, 0, gradientT);
                      }
                      else
                      {
                          t = 1;
                      }

                      var finalColor = Color.Lerp(new Color(defaultColor.r, defaultColor.g, defaultColor.b, 0), defaultColor, t);

                      cacheSB.Append("[");
                      cacheSB.Append(((int)(finalColor.r * 255)).ToString("X2"));
                      cacheSB.Append(((int)(finalColor.g * 255)).ToString("X2"));
                      cacheSB.Append(((int)(finalColor.b * 255)).ToString("X2"));
                      cacheSB.Append(((int)(finalColor.a * 255)).ToString("X2"));
                      cacheSB.Append("]");
                      cacheSB.Append(singleChar);
                      cacheSB.Append("[-]");

                      //cacheSB.AppendFormat("[{0:X2}{1:X2}{2:X2}{3:X2}]{4}[-]"
                      //    , ((int)(finalColor.r * 255))
                      //    , ((int)(finalColor.g * 255))
                      //    , ((int)(finalColor.b * 255))
                      //    , ((int)(finalColor.a * 255))
                      //    , singleChar);
                  }

                  return cacheSB.ToString();
              };

            var beginTime = Time.time;
            for (float d = duration; Time.time - beginTime <= d;)
            {
                var t = (Time.time - beginTime) / d;

                cacheSB.Length = 0;
                var r = convertSourceText(t);
                textOut(r);

                yield return null;
            }

            textOut(textIn);
        }
    }
}
